package com.alks.function.service.impl.stockdept.pcfactorystockquery;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.thread.UserIdThread;
import com.alks.common.utils.beanutils.BeanUtil;
import com.alks.common.utils.beanutils.StringUtils;
import com.alks.entity.data.entity.*;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.chengKong.export.PunchingExportVo;
import com.alks.function.data.dto.chengKong.produce.PcLotGroupDto;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.FinishRecHisDto;
import com.alks.function.data.dto.stockdept.pcfactorystockwork.FinishRecTempDto;
import com.alks.function.data.dto.sys.DeptSimpleDto;
import com.alks.function.data.request.stockdept.pcfactorystockwork.FinishRecHisRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.FinishRecStoreRequest;
import com.alks.function.data.request.stockdept.pcfactorystockwork.FinishRecTempRequest;
import com.alks.function.mapper.SdDepartmentMapper;
import com.alks.function.mapper.biocontrol.deptwork.PcExportPlanDetailMapper;
import com.alks.function.mapper.chengKong.PcLotGroupMapper;
import com.alks.function.mapper.chengKong.PcLotHeadMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.PcFinishCollectDetailMapper;
import com.alks.function.mapper.stockdept.pcfactorystockquery.PcPackTypeMapper;
import com.alks.function.service.stockdept.pcfactorystockquery.IFinishRecService;
import com.alks.function.service.system.ISysConfigService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.*;

/**
 * @author: chen
 * @date: 2024/11/12
 * @description: 成品收发
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class FinishRecServiceImpl extends ServiceImpl<PcFinishCollectDetailMapper, PcFinishCollectDetail> implements IFinishRecService {

    private final PcFinishCollectDetailMapper mapper;
    private final PcPackTypeMapper packTypeMapper;
    private final PcLotHeadMapper pcLotHeadMapper;
    private final PcLotGroupMapper pcLotGroupMapper;
    private final ISysConfigService sysConfigService;
    private final SdDepartmentMapper departmentMapper;
    private final PcExportPlanDetailMapper exportPlanDetailMapper;

    @Override
    @AutoPageAop
    public ResponseInfo finishRecTempQuery(FinishRecTempRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        // 查询分页数据
        List<FinishRecTempDto> dtos = mapper.listQuery(request, companyId);
        Page<FinishRecTempDto> page = (Page<FinishRecTempDto>) dtos;
        // 查询统计数据
        Map<String, Object> summaryRoot = mapper.summaryQuery(request, companyId);
        Map<String, Object> map = new HashMap<>(3);
        map.put("rows", page);
        map.put("total", page.getTotal());
        map.put("summaryRoot", summaryRoot);
        return ResponseInfo.ok(map);
    }

    @Override
    @AutoPageAop
    public ResponseInfo finishRecHistoryQuery(FinishRecHisRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        // 查询分页数据
        List<FinishRecHisDto> dtos = mapper.historyQuery(request, companyId);
        Page<FinishRecHisDto> page = (Page<FinishRecHisDto>) dtos;
        Map<String, Object> map = new HashMap<>(3);
        map.put("rows", page);
        map.put("total", page.getTotal());
        return ResponseInfo.ok(map);
    }

    @Override
    public List<PcPackType> selectPackTypeCombo(String searchKey) {
        String companyId = UserIdThread.get().getCompanyId();
        return packTypeMapper.selectPackTypeCombo(companyId, searchKey);
    }

    @Override
    public ResponseInfo groupNos(String lotNo, String collectType) {
        String companyId = UserIdThread.get().getCompanyId();
//        PunchingExportVo vo = pcLotHeadMapper.getPcLotHead(lotNo, companyId);
//        if (vo == null) {
//            return ResponseInfo.error("指令不存在");
//        }
        List<PcLotGroup> list = pcLotGroupMapper.selectLotGroups(lotNo, companyId, collectType);
        List<PcLotGroupDto> res = new ArrayList<>();
        list.forEach(e->{
            PcLotGroupDto dto = new PcLotGroupDto();
            BeanUtil.copyProperties(e, dto);
            res.add(dto);
        });
        return ResponseInfo.ok(res);
    }

    @Override
    public ResponseInfo delRecord(Long id) {
        if (mapper.deleteById(id) > 0) {
            return ResponseInfo.ok();
        } else {
            return ResponseInfo.error("数据删除失败");
        }
    }

    @Override
    public ResponseInfo updateFinishStore(FinishRecStoreRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        PcLotHead pcLotHead = pcLotHeadMapper.selectOne(
                new LambdaQueryWrapper<PcLotHead>().eq(PcLotHead::getLotNo, request.getLotNo())
                        .eq(PcLotHead::getCompanyId, companyId));
        if (pcLotHead == null) {
            return ResponseInfo.error("无效的指令信息，请核实!");
        }

        FinishRecTempRequest tempRequest = new FinishRecTempRequest();
        tempRequest.setLotNoFull(request.getLotNo());
        List<FinishRecTempDto> dtos = mapper.listQuery(tempRequest, companyId);
        if (dtos.size() != 1) {
            throw new ServiceErrorException("数据异常");
        }
        FinishRecTempDto dto = dtos.get(0);

        if (request.getCollectTime() == null) {
            return ResponseInfo.error(request.inStore() ? "缴库日期不能为空" : "出库日期不能为空");
        }
        PcLotGroup lotGroup = pcLotGroupMapper.selectOne(
                new LambdaQueryWrapper<PcLotGroup>()
                        .eq(PcLotGroup::getLotNo, request.getLotNo())
                        .eq(PcLotGroup::getGroupNo, request.getGroupNo()));
        if (lotGroup == null) {
            return ResponseInfo.error("无效的配码，请核查！！！");
        }
        DeptSimpleDto deptDto = null;
        if (request.inStore()) { // 入库
            if (StringUtils.isEmpty(request.getDeptNo())) {
                return ResponseInfo.error("缴库单位必填，请核查！！！");
            }
            List<DeptSimpleDto> deptInfo = departmentMapper.selectLastCombo(companyId, request.getDeptNo());
            if (deptInfo.size() != 1) {
                return ResponseInfo.error("无效的缴库单位，请核查！！！");
            } else {
                deptDto = deptInfo.get(0);
            }
            if (request.getCollectTime().isAfter(LocalDate.now())) {
                return ResponseInfo.error("缴库日期不能大于当前日期");
            }

            int needQty = dto.getOrderQty() - dto.getInQty();
            if (needQty <= 0) {
                return ResponseInfo.warn("缴库数量已满，无需操作");
            }
            if (request.getPairQty() > needQty) {
                return ResponseInfo.error("缴库数量超过入库欠数");
            }
            // 检查配码对应数量
            int groupNoSumInQty = mapper.sumStoreInByGroupNo(companyId, request.getLotNo(), lotGroup.getGroupNo().intValue());
            PcLotGroupDto groupDto = new PcLotGroupDto();
            BeanUtil.copyProperties(lotGroup, groupDto);
            if (groupNoSumInQty + request.getPairQty() > groupDto.getCount().intValue()) {
                return ResponseInfo.error("对应配码的缴库总数超过配码数");
            }
        } else {    //出库
            if (request.getCollectTime().isAfter(LocalDate.now())) {
                return ResponseInfo.error("出库日期不能大于当前日期");
            }
            String isRequired = sysConfigService.selectConfigByKey("finish.store.container.empty", "0");
            if ("1".equals(isRequired) && (
                    StringUtils.isEmpty(request.getContainerNo()) || StringUtils.isEmpty(request.getInvoiceNo()))) {
                return ResponseInfo.error("柜号和发票号必填，请核查！！！");
            }
            // 检查发票有效性
            int cfmNum = exportPlanDetailMapper.selectCfmNum(companyId, request.getInvoiceNo());
            if (cfmNum > 0) {
                return ResponseInfo.error("该发票号已船务检核，请核实！");
            }

            int needQty = dto.getOrderQty() - dto.getOutQty();
            if (needQty <= 0) {
                return ResponseInfo.warn("出库数量已满，无需操作");
            }
            int storeQty = dto.getInQty() - dto.getOutQty();
            if (request.getPairQty() > storeQty) {
                return ResponseInfo.error("出库数量超过库存数");
            }
            if (request.getPairQty() > needQty) {
                return ResponseInfo.error("出库数量超过出库欠数");
            }
        }

        List<PcFinishCollectDetail> resultList = new ArrayList<>();
        checkPacks(request, pcLotHead, resultList, deptDto, lotGroup);

        boolean result = this.saveBatch(resultList);
        return result ? ResponseInfo.ok() : ResponseInfo.error("数据更新失败");
    }

    /**
     * 校验打包数据
     * @param request
     * @param pcLotHead
     * @param resultList
     * @param deptInfo
     * @return
     */
    private void checkPacks(FinishRecStoreRequest request, PcLotHead pcLotHead, List<PcFinishCollectDetail> resultList, DeptSimpleDto deptInfo, PcLotGroup lotGroup) {
        Date now = new Date();
        if (!CollectionUtils.isEmpty(request.getPackTypes())) {
            List<PcPackType> packTypes = packTypeMapper.selectPackTypeCombo(pcLotHead.getCompanyId(), null);
            Map<String, PcPackType> packTypeMap = new HashMap<>();
            packTypes.forEach(packType -> packTypeMap.put(packType.getPackType(), packType));
            int totalQty = 0;
            for (FinishRecStoreRequest.PackType packType : request.getPackTypes()) {
                if (StringUtils.isNull(packTypeMap.get(packType.getPackType()))) {
                    throw new ServiceErrorException(StringUtils.format("【{}】无效的装箱方式", packType.getPackType()));
                }
                int caseQty = packTypeMap.get(packType.getPackType()).getCaseQty().intValue();
                if (caseQty <= 0) {
                    throw new ServiceErrorException(StringUtils.format("【{}】未定义每箱双数", packType.getPackType()));
                }
                if (packType.getCaseQty() == null || packType.getCaseQty() <= 0) {
                    throw new ServiceErrorException(StringUtils.format("【{}】箱数不能为0", packType.getPackType()));
                }
                totalQty += caseQty * packType.getCaseQty();
                PcFinishCollectDetail finishCollectDetailRecord = new PcFinishCollectDetail();
                finishCollectDetailRecord.setCompanyId(pcLotHead.getCompanyId());
                finishCollectDetailRecord.setLotNo(request.getLotNo());
                finishCollectDetailRecord.setCollectTime(request.getCollectTime().atStartOfDay());
                finishCollectDetailRecord.setCaseQty(packType.getCaseQty());
                finishCollectDetailRecord.setCollectType(request.getOptType());
                if (deptInfo != null) {
                    finishCollectDetailRecord.setLine(deptInfo.getDeptName());
                }
                finishCollectDetailRecord.setGroupNo(request.getGroupNo());
                finishCollectDetailRecord.setPackType(packType.getPackType());
                finishCollectDetailRecord.setPairQty(caseQty * packType.getCaseQty());
                finishCollectDetailRecord.setSysUser(UserIdThread.get().getUserName());
                finishCollectDetailRecord.setSysDate(LocalDateTimeUtil.of(now));
                if (!StringUtils.isNull(lotGroup.getPoNo())) {
                    finishCollectDetailRecord.setPoNo(lotGroup.getPoNo());
                } else {
                    finishCollectDetailRecord.setPoNo(request.getPoNo());
                }
                if (deptInfo != null) {
                    if ("Y".equals(deptInfo.getDeptType())) {
                        finishCollectDetailRecord.setOutDept(1);
                    } else {
                        finishCollectDetailRecord.setOutDept(0);
                    }
                }
                if (!request.inStore()) {
                    finishCollectDetailRecord.setContainerNo(request.getContainerNo());
                    finishCollectDetailRecord.setInvoiceNo(request.getInvoiceNo());
                }
                finishCollectDetailRecord.setCustomsCode(request.getCustomsCode());
                resultList.add(finishCollectDetailRecord);
            }
            if (request.getPairQty() != totalQty) {
                throw new ServiceErrorException("总双数与实际双数不符，请核实！！！");
            }
        } else {
            PcFinishCollectDetail finishCollectDetailRecord = new PcFinishCollectDetail();
            finishCollectDetailRecord.setCompanyId(pcLotHead.getCompanyId());
            finishCollectDetailRecord.setLotNo(request.getLotNo());
            finishCollectDetailRecord.setCollectTime(request.getCollectTime().atStartOfDay());
            finishCollectDetailRecord.setCollectType(request.getOptType());
            if (deptInfo != null) {
                finishCollectDetailRecord.setLine(deptInfo.getDeptName());
            }
            finishCollectDetailRecord.setGroupNo(request.getGroupNo());
            finishCollectDetailRecord.setPairQty(request.getPairQty());
            finishCollectDetailRecord.setSysUser(UserIdThread.get().getUserName());
            finishCollectDetailRecord.setSysDate(LocalDateTimeUtil.of(now));
            if (!StringUtils.isNull(lotGroup.getPoNo())) {
                finishCollectDetailRecord.setPoNo(lotGroup.getPoNo());
            } else {
                finishCollectDetailRecord.setPoNo(request.getPoNo());
            }
            if (deptInfo != null) {
                if ("Y".equals(deptInfo.getDeptType())) {
                    finishCollectDetailRecord.setOutDept(1);
                } else {
                    finishCollectDetailRecord.setOutDept(0);
                }
            }
            if (!request.inStore()) {
                finishCollectDetailRecord.setContainerNo(request.getContainerNo());
                finishCollectDetailRecord.setInvoiceNo(request.getInvoiceNo());
            }
            finishCollectDetailRecord.setCustomsCode(request.getCustomsCode());
            resultList.add(finishCollectDetailRecord);
        }
    }
}
